package com.ecarx.vhaltests.hy11.testcases.transmit;

import static com.ecarx.xui.adaptapi.car.property.IProperty.TRANSMIT_MAIN_CONTACTORS_STATUS;

import android.car.VehicleAreaType;
import android.car.hardware.CarPropertyValue;
import android.car.hardware.property.CarPropertyManager;

import androidx.test.platform.app.InstrumentationRegistry;

import com.ecarx.vhaltests.IpcpClient;
import com.ecarx.vhaltests.VhalUnitTestBase;
import com.ecarx.xui.adaptapi.car.IWrapper;
import com.ecarx.xui.adaptapi.car.property.IPropertyValue;

import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TransmitMainContactorsStatusTest extends VhalUnitTestBase {
    private static int propertyId;
    private static IWrapper.IPropertyId wrapperProperty;
    private CarPropertyManager.CarPropertyEventCallback propertyCbk;
    private static IpcpClient ipcpClient = new IpcpClient();
    private boolean isFirstCbk;
    private static final int AREA_ID = VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL;
    private int cbkValue;
    private final Object cbkLock = new Object();

    @BeforeClass
    public static void testInit() {
        IWrapper wrapper = com.ecarx.xui.adaptapi.car.Car.createWrapper(InstrumentationRegistry.getInstrumentation().getTargetContext());
        wrapperProperty = wrapper.getWrappedPropertyId(IWrapper.WrappedIdType.ID_TYPE_FUNCTION, TRANSMIT_MAIN_CONTACTORS_STATUS);
        propertyId = wrapperProperty.getPropertyId();
        Assert.assertTrue(isAvail());
    }

    @Test
    public void test001_GetTransmitMainContactorsStatusOpen() {
        testGet(IPropertyValue.MainContactorsStatus.OPEN);
    }

    @Test
    public void test002_GetTransmitMainContactorsStatusClose() {
        testGet(IPropertyValue.MainContactorsStatus.CLOSE);
    }

    @Test
    public void test003_GetTransmitMainContactorsStatusKeepSt() {
        testGet(IPropertyValue.MainContactorsStatus.KEEP_STATUS);
    }

    @Test
    public void test004_GetTransmitMainContactorsStatusOpenAndReqActvDcha() {
        testGet(IPropertyValue.MainContactorsStatus.OPEN_AND_REQ_ACTV_DCHA);
    }

    @Test
    public void test005_GetTransmitMainContactorsStatusCbk() {
        testCbk();
    }

    private void mockSignal(int value) {
        int vddmSvcId = 48;
        int[] vddmOperIds = {999};
        ipcpClient.setConfig(vddmSvcId, vddmOperIds);
        String[] vddms = {"hvSysRlyStsHvSysRlySts"};
        int[] vddmValues = {value};
        boolean vddmRet = ipcpClient.setVDDMSignal(vddmSvcId, vddmOperIds[0], vddms, vddmValues);
        Assert.assertTrue(vddmRet);
        delay();
    }

    private void testGet(int value) {
        int mockValue = 0;
        switch (value) {
            case IPropertyValue.MainContactorsStatus.OPEN:
                mockValue = 0;
                break;
            case IPropertyValue.MainContactorsStatus.CLOSE:
                mockValue = 1;
                break;
            case IPropertyValue.MainContactorsStatus.KEEP_STATUS:
                mockValue = 2;
                break;
            case IPropertyValue.MainContactorsStatus.OPEN_AND_REQ_ACTV_DCHA:
                mockValue = 3;
                break;
        }
        mockSignal(mockValue);
        Assert.assertEquals(wrapperProperty.getPropertyValue(value).intValue(), getValue());
    }

    private int getValue() {
        delay();
        return mCarPropertyMgr.getIntProperty(propertyId, AREA_ID);
    }

    private static boolean isAvail() {
        delay();
        return mCarPropertyMgr.isPropertyAvailable(propertyId, AREA_ID);
    }

    private void testCbk() {
        cbkValue = -1;
        testGet(IPropertyValue.MainContactorsStatus.OPEN);
        delay();
        int expectedValue = IPropertyValue.MainContactorsStatus.CLOSE;
        propertyCbk = new CarPropertyManager.CarPropertyEventCallback() {
            @Override
            public void onChangeEvent(CarPropertyValue carPropertyValue) {
                if (carPropertyValue.getAreaId() == AREA_ID) {
                    if (isFirstCbk) {
                        isFirstCbk = false;
                    } else {
                        cbkValue = (int) carPropertyValue.getValue();
                        unLock();
                    }
                }
            }

            @Override
            public void onErrorEvent(int i, int i1) {
            }
        };
        mCarPropertyMgr.registerCallback(propertyCbk, propertyId, CarPropertyManager.SENSOR_RATE_ONCHANGE);
        delay();
        testGet(expectedValue);
        lock();
        Assert.assertEquals(wrapperProperty.getPropertyValue(expectedValue).intValue(), cbkValue);
    }

    private void lock() {
        try {
            synchronized (cbkLock) {
                cbkLock.wait(1000);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private void unLock() {
        synchronized (cbkLock) {
            cbkLock.notify();
        }
    }

}